#include "IcemStack.h"
#include "IcemVolume.h"

#include <cstdint>
#include <ctime>

//#include <Windows.h>
//#include <Wincon.h>

IcemStack<uint8_t> stack;

extern "C" __declspec(dllexport) int ReadTalairachVolume(bool filtered, double alpha, double brightness, double contrast, unsigned char colormap[3*2000],
														 float mat[4][4], int* dim, uint16_t* data, float talairachPoints[3][9]){
	unsigned char dummy[3*256];
	std::tr1::shared_ptr<TalairachVolume > v(new TalairachVolume(dim,data,alpha,brightness,contrast,dummy,mat,talairachPoints,colormap));
	stack.AddTalairachVolume(v, filtered);
	return 0;
}

extern "C" __declspec(dllexport) int ReadVolume(int id, double alpha, double brightness, double contrast, unsigned char colormap[3*256], float mat[4][4], int* dim, uint8_t* data){
	std::tr1::shared_ptr<IcemVolume<uint8_t> > v(new IcemVolume<uint8_t>(dim,data,alpha,brightness,contrast,colormap,mat));
	stack.AddVolume(id-1,v);
	return 0;
}

extern "C" __declspec(dllexport) int GetSliceSize(int dir, int* sizeX, int* sizeY){
	return stack.GetSliceSize(dir, sizeX, sizeY);
}

extern "C" __declspec(dllexport) int GetFirstSlice(double* pos, int dir, unsigned char** result) {
	return stack.GetFirstSlice(pos, dir, (uchar3*)*result);
}

extern "C" __declspec(dllexport) int GetSlice(double* pos, int dir, unsigned char** result) {
	stack.GetSlice(pos, dir, (uchar3*)*result);
	return 0;

}

extern "C" __declspec(dllexport) int SetAlpha(int id, float alpha) {
	stack.SetAlpha(id-1,alpha);
	return 0;
}

extern "C" __declspec(dllexport) int SetBrightness(int id, float b) {
	stack.SetBrightness(id-1,b);
	return 0;
}

extern "C" __declspec(dllexport) int SetContrast(int id, float c) {
	stack.SetContrast(id-1,c);
	return 0;
}

extern "C" __declspec(dllexport) int SetColormap(int id, float cm[3*256]) {
	unsigned char cm2[3*256];
	for (int i=0;i<3*256;++i) {
		if (cm[i]==1.0f) {
			cm2[i]=255;
		} else {
			cm2[i]=unsigned char(floor(cm[i]*256.f));
		}
	}
	stack.SetColormap(id-1,cm2);
	return 0;
}


extern "C" __declspec(dllexport) int SetTalairachColormap(float cm[3*2000]) {
	unsigned char cm2[3*2000];
	for (int i=0;i<3*2000;++i) {
		if (cm[i]==1.0f) {
			cm2[i]=255;
		} else {
			cm2[i]=unsigned char(floor(cm[i]*256.f));
		}
	}
	stack.SetTalairachColormap(cm2);
	return 0;
}

extern "C" __declspec(dllexport) int SetFilterLimits (int id, float lowerLimit, float upperLimit) {
  stack.SetFilterLimits(id-1,lowerLimit,upperLimit);
  return 0;
}

extern "C" __declspec(dllexport) int SetTransformationMatrix (int id, float mat[4][4]) {
 stack.SetTransformationMatrix(id-1,mat);
 return 0;
}


extern "C" __declspec(dllexport) int GetRenderedVolumesNumberAndSize (int* number, int* X, int* Y, int* Z ) {
 stack.GetVolumesNumberAndSize(number,X,Y,Z);
 return 0;
}


//returns every volume in MRI coordinates space
extern "C" __declspec(dllexport) const char** GetRenderedVolumes (uint8_t** volumes, double** transformationMatrix) {
	 const char** names;
	 stack.GetRenderedVolumes(*volumes, &names, transformationMatrix);
	 return names;
}
